import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Reader;

/**
  * Demonstrate piped streams. Data is read from file and
  * read and "analysized" by one thread, which in turn passes
  * its result via a pipe to a second thread for further analysis.
  * This thread in turn passes its data via a pipe to a method
  * for output to a file.
**/
public class PipedAnalyzer {

  public static void main(String[] args) throws IOException {

    File file = null;

     // Get the file from the argument line.
    file = new File ("dataInput.txt");
//    if (args.length > 0) 
//    if (file == null) {
//      System.out.println ("Input data file required");
//      System.exit (0);
//    }
    // Create a file reader for the data file.
    FileReader file_in = new FileReader (file);

    // Carry out the two levels of analysis and then
    // write out the results.
    analyzeOut (analyze2 (analyze1 (file_in)));

    // Close the file stream.
    file_in.close();

  } // main

  /** Set up the piped streams for the first thread. Then create and
    * start the thread. 
   **/
  public static Reader analyze1 (Reader source)
       throws IOException {

    // Buffer the input data.
    BufferedReader buf_in = new BufferedReader (source);

    // Create a pipe for data sent out by the Analyze1Thread
    PipedWriter pipe_out = new PipedWriter ();

    // What goes into the pipe can be read by the other thread via pipe_in
    PipedReader pipe_in = new PipedReader (pipe_out);

    // Start the thread for the first level analysis. It
    // will take data from buf_in and write it into pipe_out.
    new Analyze1Thread (pipe_out, buf_in).start ();

    // The other thread will be able to read via pipe_in what
    // was written into pipe_out.
    return pipe_in;

  } // analyze1

  /** Set up the piped streams for the second thread. Then create and
    * start the thread. 
   **/ 
  public static Reader analyze2 (Reader source) throws IOException {

    // Buffer the input data.
    BufferedReader buf_in = new BufferedReader (source);

    // Create a pipe for data sent out by the Analyze2Thread
    PipedWriter pipe_out = new PipedWriter ();

    // What goes into the pipe can be read by the other thread via pipe_in
    PipedReader pipe_in = new PipedReader (pipe_out);

    // Start the thread for the second level analysis. It
    // will take data from buf_in and write it into pipe_out.
    new Analyze2Thread  (pipe_out, buf_in).start ();

    // The other thread will be able to read via pipe_in what
    // was written into pipe_out.
    return pipe_in;

  } // analyze2

  /**
    * Read the output from the final analysis step and print to
    * the console.
   **/
  public static void analyzeOut (Reader source) throws IOException {

    // Buffer the input data.
    BufferedReader buf_in = new BufferedReader (source);
    System.out.println ("PipedAnalysis Output:");

    String result;
    while ((result = buf_in.readLine ()) != null)
         System.out.println (result);
    buf_in.close ();

  } // analyzeOut

} // PipedAnalyzer